package rank;

import java.util.HashMap;
import java.util.Map;

import system.Config;
import system.L;
import data.DBPlayer;
import data.PlayerCache;

public class PVPRank extends AbstractRank {
	
//	private PlayerCache _playerCache = new PlayerCache();

	private Map<String, PVPRankNode> nodes = new HashMap<String, PVPRankNode>();
//	public RankNode[] gradeNodes = new RankNode[Config.gradeScore.length];
//	public RankNode[] randomItes = new RankNode[Config.gradeScore.length];
	
	public int randomRangeMax = Integer.MAX_VALUE;

	public PVPRank() {
		super();
//		RankPlayer player;
//		RankNode node;
//		for (int i = 0; i < Config.gradeScore.length; i++) {
//			player = new RankPlayer();
//			player.pvpScore = Config.gradeScore[i];
//			player.pvpWinPercent = Byte.MIN_VALUE;
//			player.level = Integer.MIN_VALUE;
//			node = new PVPRankNode(player);
//			pushBack(node);
//			gradeNodes[i] = node;
//			randomItes[i] = node;
//		}
	}
	
//	public int isRandomIteNode(PVPRankNode node) {
//		for (int i = 0; i < Config.gradeScore.length; i++) {
//			if (randomItes[i] == node) return i;
//		}
//		return -1;
//	}
	
	public synchronized void clearCache(PlayerCache cache) {
//		if (count() < Config.CACHE_MAX_COUNT) 
//			return;
//		PVPRankNode node = (PVPRankNode) last.font;
//		long now = System.currentTimeMillis();
//		while (node != first) {
//			if (node.isGradeNode()) 
//			{
//				node = (PVPRankNode) node.font;
//				continue;
//			}
//			if (now - node.player.lastEnterPVPTime > Config.KICK_CACHE_TIME) {
//				remove(node);
//				cache.remove(node.player);				
//			} 
//			node = (PVPRankNode) node.font;				
//			if (count() < Config.CACHE_MAX_COUNT)
//				break;
//		}
	}
	
	synchronized public void updateLevel(String guid, int level) {
		PVPRankNode node = nodes.get(guid);
		if (node != null) {
			node.level = level;
			super.update(node);
		}
	}

	synchronized public void updatePVP(DBPlayer player) {
		PVPRankNode node = nodes.get(player.getGUID());
		if (node != null) {
			node.pvpWinPercent = player.getWinPercent();
			node.pvpScore = player.getPvpScore();
			node.level = player.getLevel();
			super.update(node);
			return;
		}
		node = new PVPRankNode();
		node.name = player.getName();
		node.guid = player.getGUID();
		node.sex = player.getSex();
		node.level = player.getLevel();
		node.pvpScore = player.getPvpScore();
		node.pvpWinPercent = player.getWinPercent();
		super.pushBack(node);
		nodes.put(node.guid, node);
		if (count() > Config.PVP_RANK_CAPACITY) {
			PVPRankNode pp = (PVPRankNode)pop();
			if (pp != null)
				nodes.remove(pp.guid);
		}
	}
	
	@Override
	protected RankNode initFirstNode() {
		PVPRankNode node = new PVPRankNode();
		node.pvpScore = Integer.MAX_VALUE;
		return node;
	}

	@Override
	protected RankNode initLastNode() {
		PVPRankNode node = new PVPRankNode();
		node.pvpScore = Integer.MIN_VALUE;
		return node; 
	}

	synchronized public void checkRanking() {
		PVPRankNode ite = (PVPRankNode) last.font;
		while (ite != first) {
			if (ite.getRanking() != ite.font.getRanking() + 1)
				L.error("error ranking" + ite.name);
			ite = (PVPRankNode) ite.font;
		}
	}

	synchronized public void printRanking() {
		RankNode ite = first.back;
		PVPRankNode player;
		while (ite != last) {
			player = (PVPRankNode)ite;
			System.out.println("[RANK] guid(" + player.guid + ") name(" + player.name + ") rank("
					+ ite.getRanking() + ") realrank(" + player.getRanking()
					+ ") score(" + player.pvpScore + ")" + " grade("
					+ Config.getPVPLevel(player.pvpScore)+ ")");
			ite = ite.back;
		}
		System.out.println("[pvp conunt]" + count() + ":" + nodes.size());
	}
	
	synchronized public void printStatus() {
		L.info("rank size:"+nodes.size());
	}
	
//	public int selectChallenge(int pvpLevel, RankPlayer[] result, int offset, int tcount,
//			RankPlayer except) {
//		RankNode min = gradeNodes[pvpLevel];
//		RankNode ite = min;
//		RankNode max;
//		if (pvpLevel < Config.gradeScore.length - 1) {
//			max = gradeNodes[pvpLevel + 1];
//		} else {
//			max = first;
//		}
//		int count = min.getRanking() - max.getRanking() - 1;
//		int stepMax = Math.min(count/tcount, randomRangeMax);		
//		if (except.pvpLevel == pvpLevel)
//			count--;
//		count = Math.min(count, tcount);
//		int step;
//		for (int i = 0; i < count; i++) {
//			step = (int)(Math.random()*stepMax) + 1;
//			ite = jump(ite, step, min, max);
//			if (((PVPRankNode) ite).player.guid.equals(except.guid))
//				ite = jump(ite, 1, min, max);
//			result[i + offset] = ((PVPRankNode) ite).player;
//		}
//		return count;
////		randomItes[pvpLevel] = ite;
//	}
	
//	private RankNode jump(RankNode from, int count, RankNode min, RankNode max) {
//		RankNode ite = from;
//		for (int i = 0; i < count; i++) {
//			ite = ite.font;
//			if (ite == max || ite == min)
//				ite = min.font;
//		}
//		return ite;
//	}

//	public synchronized RankPlayer[] getChallengeList(RankPlayer player) {
//		int count = Config.PVP_RANDOM_COUNT_PER_LEVEL * 3;
//		RankPlayer[] result = new RankPlayer[count];
//		
//		if (player.pvpRank == -1) {
//			return result;
//		}
//		
//		int level = player.pvpLevel;
//		while (level >= 0) {
//			count -= selectChallenge(level, result, result.length-count, count, player);
//			level--;
//			if (count == 0) break;
//		}
//		
////		if (player.pvpLevel > 0) {
////			selectChallenge(player.pvpLevel - 1, result, 0, Config.PVP_RANDOM_COUNT_PER_LEVEL, player);
////			selectChallenge(player.pvpLevel, result, count, Config.PVP_RANDOM_COUNT_PER_LEVEL, player);
////		}
////		else 
////			selectChallenge(player.pvpLevel, result, 0, Config.PVP_RANDOM_COUNT_PER_LEVEL*2, player);
////
////		if (player.pvpLevel < Config.gradeScore.length - 1) {
////			selectChallenge(player.pvpLevel + 1, result, count * 2, Config.PVP_RANDOM_COUNT_PER_LEVEL, player);
////		} else {
////			selectChallenge(player.pvpLevel, result, count * 2, Config.PVP_RANDOM_COUNT_PER_LEVEL, player);
////		}
//
//		return result;
//	}
	
	synchronized public PVPRankNode findByID(String guid) {
		return nodes.get(guid);
	}
	
	synchronized public void removePlayer(String guid) {
		PVPRankNode node = nodes.remove(guid);
		if (node != null) {
			super.remove(node);
			L.info("remove player from pvp rank:"+guid);
		}
	}
}
